package com.smm.web.vmc.service.impl;

import com.smm.web.vmc.dao.BaseDao;
import com.smm.web.vmc.domain.*;
import com.smm.web.vmc.domain.relation.CameraReceiptRelation;
import com.smm.web.vmc.dto.AlamQueryDto;
import com.smm.web.vmc.service.*;
import com.smm.web.vmc.util.GePushUtil;
import com.smm.web.vmc.util.SMSUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by zhenghao on 2016/9/5.
 *
 */
@Slf4j
@Service
public class AlamServiceImpl implements AlamService {



    @Resource
    private BaseDao<Alam> alamBaseDao;

    @Resource
    private ReceiptService receiptService;

    @Resource
    private UserReceiptRelationService userReceiptRelationService;

    @Resource
    private CameraReceiptRelationService cameraReceiptRelationService;

    @Resource
    private CameraService cameraService;

    @Resource
    private TagService tagService;


    @Override
    public List<Alam> getAlamListByUser(int userId) {

        //通过用户编号获取仓单编号列表
        List<Receipt> receipts = receiptService.getReceiptsByUser(userId);

        if(receipts==null || receipts.size()==0) return null;

        List<String> receiptNos = receipts.stream().map(Receipt::getNo).collect(Collectors.toList());

        //通过仓单编号获取报警记录列表
        DetachedCriteria where = DetachedCriteria.forClass(Alam.class);
        where.add(Restrictions.in("receipt.no", receiptNos));
        where.addOrder(Order.desc("alamTime"));
        List<Alam> alams = alamBaseDao.query(where);

        return alams;
    }

    @Override
    public List<Alam> queryByQueryAndUser(AlamQueryDto queryDto, int userId) {

        //通过查询条件获取仓单
        List<Receipt> receipts = receiptService.getReceiptsByQueryAndUser(queryDto,userId);

        if(receipts==null || receipts.size()==0) return null;

        List<String> receiptNos = receipts.stream().map(Receipt::getNo).collect(Collectors.toList());

        //通过仓单编号获取对应报警记录
        DetachedCriteria where = DetachedCriteria.forClass(Alam.class);
        where.add(Restrictions.in("receipt.no", receiptNos));

        //如果有处理状态查询条件
        if(queryDto.getStatus()>0){
            where.add(Restrictions.eq("status",queryDto.getStatus()));
        }

        where.addOrder(Order.desc("alamTime"));

        return alamBaseDao.query(where);
    }

    @Override
    public Alam getOneById(int alamId) {

        return alamBaseDao.getOne(Alam.class,alamId);
    }

    @Override
    public List<Alam> getAlamListByRep(String repNo) {

        DetachedCriteria where = DetachedCriteria.forClass(Alam.class);
        where.add(Restrictions.eq("receipt.no", repNo));
        where.addOrder(Order.desc("alamTime"));

        return alamBaseDao.query(where);
    }

    @Override
    public Map<String, List<Alam>> getGroupByDateForRep(String repNo) {

        List<Alam> alamList = this.getAlamListByRep(repNo);

        LinkedHashMap<String,List<Alam>> groupAlamMap  = new LinkedHashMap<>();

        //按日期分组
        if(!alamList.isEmpty()){

            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

            for(Alam alam :alamList){

                //格式化报警日期
                String date = format.format(alam.getAlamTime());

                //检查这个日期在map 的key 中是否存在
                if(groupAlamMap.keySet().contains(date)){

                    //已经存在, 保存报警记录
                    groupAlamMap.get(date).add(alam);

                }else{

                    //不存在，保存key and  报警记录
                    List<Alam> list = new ArrayList<>();

                    list.add(alam);

                    groupAlamMap.put(date,list);

                }

            }
        }

        return groupAlamMap;
    }

    @Override
    public void process(int id, String desc) throws Exception {

        if(id==0) throw new Exception("报警记录编号不能为空");

        if(StringUtils.isBlank(desc)) throw new Exception("处理意见不能为空");

        Alam alam = alamBaseDao.getOne(Alam.class,id);

        alam.setStatus(Alam.PROCESS_STATUS_YES);
        alam.setProcessTime(new Date());
        alam.setProcessDesc(desc.trim());

        alamBaseDao.update(alam);

        //通知报警已处理
//        new GePushUtil().sendAll("报警处理通知","仓单："+alam.getReceipt().getNo()+" 报警信息已经处理");

        //推送报警信息到仓单关联用户
        List<User> userList = this.userReceiptRelationService.getUserByReceipt(alam.getReceipt().getNo());

        new GePushUtil().sendByUserList("报警处理通知","仓单："+alam.getReceipt().getNo()+" 报警信息已经处理",userList);

//        GePushUtil gePushUtil = new GePushUtil();
//
//        //循环推送
//        for(User user:userList){
//
//            gePushUtil.sendByUser("报警处理通知","仓单："+alam.getReceipt().getNo()+" 报警信息已经处理",user);
//        }

    }

    @Override
    public void add(Alam alam) throws Exception {

        alamBaseDao.add(alam);
    }

    @Override
    @Transactional
    public List<Alam> getPagerAlamListByUser(int userId, Pager pager) {

        //通过用户编号获取仓单编号列表
        List<Receipt> receipts = receiptService.getReceiptsByUser(userId);

        if(receipts==null || receipts.size()==0) return null;

        List<String> receiptNos = receipts.stream().map(Receipt::getNo).collect(Collectors.toList());

        //通过仓单编号获取报警记录列表
        DetachedCriteria where = DetachedCriteria.forClass(Alam.class);
        where.add(Restrictions.in("receipt.no", receiptNos));
        where.addOrder(Order.desc("alamTime"));

        //获取总页数
        Criteria criteria = where.getExecutableCriteria(alamBaseDao.getTemplate().getSessionFactory().getCurrentSession());

        Object count = criteria.setProjection(Projections.rowCount()).uniqueResult();

        pager.setRowCount(Integer.parseInt(count.toString()));

        log.info(String.valueOf(pager));


        //获取查询开始记录数
        int queryIndex = pager.firstResultIndex();

        log.info("----queryIndex:"+queryIndex);

        //执行查询
        criteria.setProjection(null);

        return criteria.setFirstResult(queryIndex).setMaxResults(pager.getPageSize()).list();

    }

    @Transactional
    @Override
    public void deleteAllByTag(String tagNo) {

        DetachedCriteria where = DetachedCriteria.forClass(Alam.class);
        where.add(Restrictions.eq("tag.no", tagNo));

        List<Alam> alams = this.alamBaseDao.query(where);

        //循环删除所有报警信息
        for(Alam alam:alams){

            this.alamBaseDao.delete(alam);
        }

    }

    @Override
    public void deleteAllByReceipt(String repNo) throws Exception {

        DetachedCriteria where = DetachedCriteria.forClass(Alam.class);
        where.add(Restrictions.eq("receipt.no", repNo));

        List<Alam> alams = this.alamBaseDao.query(where);

        //循环删除所有报警信息
        for(Alam alam:alams){

            this.alamBaseDao.delete(alam);
        }

    }

    @Override
    public void recive(String repNo) throws Exception {

        //获取仓单对象
        Receipt receipt = this.receiptService.getOneById(repNo);

        if(receipt==null) throw new Exception("编号为："+repNo+"仓单不存在");

        //获取仓单绑定的摄像头
        List<CameraReceiptRelation>  cameraReceiptRelations  = this.cameraReceiptRelationService.getAllByReceipt(repNo);

        if(cameraReceiptRelations==null || cameraReceiptRelations.size()==0) throw new Exception("仓单没有绑定摄像头");

        Camera camera = cameraReceiptRelations.get(0).getCamera();

        //执行抓拍
        String captureImageUrl = this.cameraService.captureByAPI(camera);

        //测试代码，增加一个rfid 对象
        String tagNo = "03000011";
        Tag tag = this.tagService.getOneById(tagNo);

        //保存报警信息
        Alam alam = new Alam();
        alam.setTag(tag);
        alam.setAlamTime(new Date());
        alam.setCaptureImageUrl(captureImageUrl);
        alam.setReceipt(receipt);

        this.add(alam);

        //推送报警信息到仓单关联用户
        List<User> userList = this.userReceiptRelationService.getUserByReceipt(receipt.getNo());

        new GePushUtil().sendByUserList("仓单报警通知","仓单："+receipt.getNo()+" 发生震动报警",userList);

        log.info("app推送通知发送完成. 仓单编号："+receipt.getNo());

        //发送短信通知
        log.info("发送短信通知. 仓单编号："+receipt.getNo());

        SMSUtil.send(userList,receipt.getNo(),new Date());

        log.info("短信发送完成");

    }
}
